﻿using AutoUI;
using Mapster;
using MESPro.Controls;
using MESPro.DBManager;
using MESPro.Models;
using RM.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using MESPro.Global;
using SqlSugar;
using MiniExcelLibs;
using System.IO;
using System.Security.Cryptography;
using MESPro.Enums;
using System.ComponentModel.Design;

namespace MESPro.Views
{
    public partial class RuningFrm : DockContent
    {

        #region Public Constructors

        /// <summary>
        /// 
        /// </summary>
        public RuningFrm()
        {
            InitializeComponent();
            DoubleBuffered = true;
            // this.Load += RuningFrm_Load;
        }

        private async void RuningFrm_Load(object sender, EventArgs e)
        {
            await QueryAll();
        }

        #endregion Public Constructors

        #region 字段

        private Function? function = new Function();

        /// <summary>
        /// 选中的主键Id
        /// </summary>
        int id = 0;

        #endregion 字段

        #region 属性

        /// <summary>
        /// 
        /// </summary>
        public Function? Function
        {
            get => function;
            set
            {
                if (value != null)
                {
                    function = value;

                    //todo  以后这里根据  function.FunctionType 选择,可以根据数据库生成,也可以根据插件反射生成页面
                }

            }
        }

        #endregion 属性

        #region Public 方法

        /// <summary>
        /// 
        /// </summary>
        public void BuildView()
        {
            if (function != null)
            {
                等到数据后刷新界面(function.TreeControls);
            }
        }

        #endregion Public 方法

        #region Private 方法

        /// <summary>
        /// 将数据库中的数据变成一个个控件
        /// </summary>
        private void 等到数据后刷新界面(List<DbControl> tree)
        {
            //var cons = await Task.Run(() =>
            //{
            //    return DbContext.Db.Queryable<DbControlG>()
            //       .Where(g => g.FunctionId == Function!.Id)
            //       .Select(it => it.TreeCode).ToList().Cast<object>().ToArray();
            //});
            //var tree = await Task.Run(() =>
            //{
            //    return DbContext.Db.Queryable<DbControlG>()
            //    .Where(g => g.FunctionId == Function!.Id)
            //    .ToTree(it => it.Child, it => it.ParentId, 0);
            //});
            //await Task.Delay(2000);
            #region 优化界面生成 todo 还需要优化
            // this.TSContainer.ContentPanel.SuspendLayout();
            //this.TSContainer.TopToolStripPanel.SuspendLayout();
            //this.TSContainer.SuspendLayout();
            //this.toolStrip1.SuspendLayout();
            //this.SuspendLayout();
            #endregion
            // await Task.Delay(2000);

            DbControlToControl(this.TSContainer.ContentPanel, tree);

            //await Task.Delay(3000);
            // QueryAll();
            #region 优化界面生成 todo
            //this.TSContainer.ContentPanel.ResumeLayout();
            //this.TSContainer.TopToolStripPanel.ResumeLayout(false);
            //this.TSContainer.TopToolStripPanel.PerformLayout();
            //this.TSContainer.ResumeLayout(false);
            //this.TSContainer.PerformLayout();
            //this.toolStrip1.ResumeLayout(false);
            //this.toolStrip1.PerformLayout();
            //this.ResumeLayout(false);
            #endregion

        }



        /// <summary>
        /// 递归数据库控件树,生成实际控件;控件不同,添加不同
        /// </summary>
        /// <param name="Panel"></param>
        /// <param name="child"></param>
        private void DbControlToControl(Control Panel, List<DbControl> child)
        {
            //ufo 添加新控件 运行时 db to control,事件处理在这里
            foreach (var item in child)
            {
                if (item.Style.FullName == typeof(RMPanel).FullName)
                {
                    var control = DBControlToControl<RMPanel>(Panel, item);
                    if (item.Child != null)
                    {

                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMTabcontrol).FullName)
                {
                    var control = DBControlToControl<RMTabcontrol>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMDateTimePicker).FullName)
                {
                    var control = DBControlToControl<RMDateTimePicker>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMGroupBox).FullName)
                {
                    var control = DBControlToControl<RMGroupBox>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMButton).FullName)
                {
                    var control = DBControlToControl<RMButton>(Panel, item);
                    control.Click += (s, e) =>
                    {
                        var btn = s as RMButton;
                        var stName = btn.StoredProcedure.StoreName;
                        var stParms = btn.StoredProcedure.StoreParms;
                        List<SugarParameter> sps = new List<SugarParameter>();
                        sps = GetParameters(stParms);
                        if (btn.MsgBoxOption.IsShowBox)
                        {
                            DialogResult res = MessageBox.Show(btn.MsgBoxOption.Content, btn.MsgBoxOption.Title, btn.MsgBoxOption.MessageBoxButtons);

                            SugarParameter psid = new SugarParameter("DialogResult", res.ToString());
                            sps.Add(psid);
                        }
                        var tab = DbContext.Db.Ado.UseStoredProcedure().GetDataTable(stName, sps);
                        var rmsg = sps.FirstOrDefault(x => x.ParameterName == "@rmsg");
                        if (rmsg != null)
                        {
                            var msg = rmsg.Value.ToString();
                            if (msg.StartsWith("弹出"))
                            {
                                MessageBox.Show(msg.Substring(2));
                            }
                            else
                            {
                                MainClientFrm.RMShowMsg?.Invoke(msg, MsgLevel.Trace);
                            }

                        }
                        TableChange(tab);
                    };
                    //if (item.Child != null)
                    //{
                    //    DbControlToControl(control, item.Child);
                    //}
                }
                else if (item.Style.FullName == typeof(RMCheckBox).FullName)
                {
                    var control = DBControlToControl<RMCheckBox>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMRadioButton).FullName)
                {
                    var control = DBControlToControl<RMRadioButton>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }

                else if (item.Style.FullName == typeof(RMTextBox).FullName)
                {
                    var control = DBControlToControl<RMTextBox>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMLabel).FullName)
                {
                    var control = DBControlToControl<RMLabel>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMComboBox).FullName)
                {
                    //ufo 默认会把datasource赋值
                    var control = DBControlToControl<RMComboBox>(Panel, item);
                    if (control.DataFrom == Enums.DataFrom.存储过程)
                    {
                        if (control.StoredProcedure != null && control.StoredProcedure.StoreParms != null)
                        {
                            control.DataSource = null;
                            control.DataSource = DbContext.Db.Ado.UseStoredProcedure().GetDataTable(control.StoredProcedure.StoreName, GetParameters(control.StoredProcedure.StoreParms));
                            control.DisplayMember = "value";
                        }

                    }
                    else
                    {

                    }
                    //根据实际清空,数据源来自于固定还是数据库,取决于一个属性
                    //如来来自于数据库,
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMPdf).FullName)
                {
                    var control = DBControlToControl<RMPdf>(Panel, item);
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMPictureBox).FullName)
                {
                    var control = DBControlToControl<RMPictureBox>(Panel, item);
                    if (File.Exists(item.Style.ImageSource))
                    {
                        control.Image = Image.FromFile(item.Style.ImageSource);
                    }

                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMDataGridView).FullName)
                {
                    var control = DBControlToControl<RMDataGridView>(Panel, item);
                    control.RMRowSelect += RowSelect;
                    control.dgv.ScrollBars = ScrollBars.Both;
                    if (item.Child != null)
                    {
                        DbControlToControl(control, item.Child);
                    }
                }
                else if (item.Style.FullName == typeof(RMLabelTextBox).FullName)
                {
                    var control = DBControlToControl<RMLabelTextBox>(Panel, item);
                    // control.Title = item.Style.DisLanguage.GetDisplayName();
                    //control.Text = "";
                    //if (item.Child != null)
                    //{
                    //    DbControlToControl(control, item.Child);
                    //}
                }

            }

        }


        /// <summary>
        /// 根据dbstyle生成一个控件,并放到容器中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="page"></param>
        /// <param name="dbcontrol"></param>
        T DBControlToControl<T>(Control page, DbControl dbcontrol) where T : Control, new()
        {
            T control = new T();
            var ss = dbcontrol.Style.Adapt(control);//将style的属性赋值给btn
            dbcontrol.Style.Adapt(control);
            //ufo 添加新控件 运行时db to control,属性初始化
            if (control is RMLabelTextBox lt)
            {
                lt.Title = dbcontrol.Style.DisLanguage.GetDisplayName();
            }
            else if (control is RMTextBox t)
            {

            }
            else if (control is RMDateTimePicker dtp)
            {
                dtp.dateTimePicker1.Value = DateTime.Now;
            }
            else
            {
                control.Text = dbcontrol.Style.DisLanguage.GetDisplayName();
            }

            //control.Click += (s, e) =>
            //{
            //    MainServerFrm.RMControlClick?.Invoke(s);
            //};
            page.Controls.Add(control);
            // control.AddMove();
            return control;
        }

        /// <summary>
        /// 根据存储过程生成页面,待测试优化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GeneratePageByStoreProc(object sender, EventArgs e)
        {
            ShowStoreProcedureLIst frm = new();
            frm.ShowDialog();
            var stname = frm.StoreProcedureName;
            var xxx = SqlHelperParameterCache.GetSpParameterSet(DbContext.conString, "test6");
            this.TSContainer.ContentPanel.Controls.Clear();
            int top = 0;
            FlowLayoutPanel panel = new FlowLayoutPanel();
            panel.Dock = DockStyle.Fill;
            foreach (var item in xxx)
            {
                switch (item.SqlDbType)
                {
                    case SqlDbType.BigInt:
                        break;
                    case SqlDbType.Binary:
                        break;
                    case SqlDbType.Bit:
                        break;
                    case SqlDbType.Char:
                        break;
                    case SqlDbType.DateTime:
                        break;
                    case SqlDbType.Decimal:
                        break;
                    case SqlDbType.Float:
                        break;
                    case SqlDbType.Image:
                        break;
                    case SqlDbType.Int:
                        break;
                    case SqlDbType.Money:
                        break;
                    case SqlDbType.NChar:
                        break;
                    case SqlDbType.NText:
                        break;
                    case SqlDbType.NVarChar:
                        break;
                    case SqlDbType.Real:
                        break;
                    case SqlDbType.UniqueIdentifier:
                        break;
                    case SqlDbType.SmallDateTime:
                        break;
                    case SqlDbType.SmallInt:
                        break;
                    case SqlDbType.SmallMoney:
                        break;
                    case SqlDbType.Text:
                        break;
                    case SqlDbType.Timestamp:
                        break;
                    case SqlDbType.TinyInt:
                        break;
                    case SqlDbType.VarBinary:
                        break;
                    case SqlDbType.VarChar:
                        break;
                    case SqlDbType.Variant:
                        break;
                    case SqlDbType.Xml:
                        break;
                    case SqlDbType.Udt:
                        break;
                    case SqlDbType.Structured:
                        break;
                    case SqlDbType.Date:
                        break;
                    case SqlDbType.Time:
                        break;
                    case SqlDbType.DateTime2:
                        break;
                    case SqlDbType.DateTimeOffset:
                        break;
                    default:
                        break;
                }
                //switch (item.DbType)
                //{
                //    case DbType.AnsiString:
                //        break;
                //    case DbType.Binary:
                //        break;
                //    case DbType.Byte:
                //        break;
                //    case DbType.Boolean:
                //        break;
                //    case DbType.Currency:
                //        break;
                //    case DbType.Date:
                //        break;
                //    case DbType.DateTime:
                //        break;
                //    case DbType.Decimal:
                //        break;
                //    case DbType.Double:
                //        break;
                //    case DbType.Guid:
                //        break;
                //    case DbType.Int16:
                //        break;
                //    case DbType.Int32:
                //        break;
                //    case DbType.Int64:
                //        break;
                //    case DbType.Object:
                //        break;
                //    case DbType.SByte:
                //        break;
                //    case DbType.Single:
                //        break;
                //    case DbType.String:
                //        break;
                //    case DbType.Time:
                //        break;
                //    case DbType.UInt16:
                //        break;
                //    case DbType.UInt32:
                //        break;
                //    case DbType.UInt64:
                //        break;
                //    case DbType.VarNumeric:
                //        break;
                //    case DbType.AnsiStringFixedLength:
                //        break;
                //    case DbType.StringFixedLength:
                //        break;
                //    case DbType.Xml:
                //        break;
                //    case DbType.DateTime2:
                //        break;
                //    case DbType.DateTimeOffset:
                //        break;
                //    default:
                //        break;
                //}
                RMTextBox textBox = new RMTextBox();
                textBox.Click += (s, e) =>
                {
                    MainServerFrm.RMControlClick?.Invoke(s);
                };
                textBox.Name = item.ParameterName;
                textBox.Top = top;
                textBox.Margin = new Padding(15);
                top += 30;
                panel.Controls.Add(textBox);

            }
            this.TSContainer.ContentPanel.Controls.Add(panel);
        }

        private async void 新增(object sender, EventArgs e)
        {
            //ufo 每个页面都对应有增删改查4个存储过程
            if (this.function == null) return;
            var stName = this.function.InsertStoredProcedure.StoreName;
            var stParms = this.function.InsertStoredProcedure.StoreParms;
            var ps = GetParameters(stParms);
            var xx = DbContext.Db.Ado.UseStoredProcedure().ExecuteCommand(stName, ps);

            var rmsg = ps.FirstOrDefault(x => x.ParameterName == "rmsg");
            if (rmsg != null)
            {
                var msg = rmsg.Value.ToString();
                if (msg.StartsWith("弹出"))
                {
                    MessageBox.Show(msg.Substring(2));
                }
                else
                {
                    MainClientFrm.RMShowMsg?.Invoke(msg, MsgLevel.Trace);
                }
            }
            id = 0;
            await QueryAll();
        }
        private async void 删除(object sender, EventArgs e)
        {
            if (id == 0)
            {
                MainClientFrm.RMShowMsg?.Invoke("请选择一个数据", MsgLevel.Info);
            }
            if (this.function == null) return;

            var stName = this.function.DeleteStoredProcedure.StoreName;
            var stParms = this.function.DeleteStoredProcedure.StoreParms;
            var ps = GetParameters(stParms);

            var xx = DbContext.Db.Ado.UseStoredProcedure().ExecuteCommand(stName, ps);
            var rmsg = ps.FirstOrDefault(x => x.ParameterName == "rmsg");
            if (rmsg != null)
            {
                var msg = rmsg.Value.ToString();
                if (msg.StartsWith("弹出"))
                {
                    MessageBox.Show(msg.Substring(2));
                }
                else
                {
                    MainClientFrm.RMShowMsg?.Invoke(msg, MsgLevel.Trace);
                }
            }
            id = 0;
            await QueryAll();
        }
        private async void 修改(object sender, EventArgs e)
        {
            if (id == 0)
            {
                MainClientFrm.RMShowMsg?.Invoke("请选择一个数据", MsgLevel.Info);
            }
            if (this.function != null)
            {
                var stName = this.function.UpdateStoredProcedure.StoreName;
                var stParms = this.function.UpdateStoredProcedure.StoreParms;
                var ps = GetParameters(stParms);

                var xx = DbContext.Db.Ado.UseStoredProcedure().ExecuteCommand(stName, ps);
                var rmsg = ps.FirstOrDefault(x => x.ParameterName == "rmsg");
                if (rmsg != null)
                {
                    var msg = rmsg.Value.ToString();
                    if (msg.StartsWith("弹出"))
                    {
                        MessageBox.Show(msg.Substring(2));
                    }
                    else
                    {
                        MainClientFrm.RMShowMsg?.Invoke(msg, MsgLevel.Trace);
                    }
                }
                await QueryAll();
            }

        }
        private async void Query(object sender, EventArgs e)
        {
            await QueryAll();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task QueryAll()
        {
            if (this.function == null) return;
            var stName = this.function.QueryStoredProcedure.StoreName;
            var stParms = this.function.QueryStoredProcedure.StoreParms;
            if (string.IsNullOrEmpty(stName)) return;
            List<SugarParameter> ps = new List<SugarParameter>();
            if (stParms != null)
            {
                ps = GetParameters(stParms);
            }
            var tab = await Task.Run(() =>
            {
                return DbContext.Db.Ado.UseStoredProcedure().GetDataTable(stName, ps);
            });




            var rmsg = ps.FirstOrDefault(x => x.ParameterName == "rmsg");
            if (rmsg != null)
            {
                var msg = rmsg.Value.ToString();
                if (msg.StartsWith("弹出"))
                {
                    MessageBox.Show(msg.Substring(2));
                }
                else
                {
                    MainClientFrm.RMShowMsg?.Invoke(msg, MsgLevel.Trace);
                }

            }
            TableChange(tab);
        }

        /// <summary>
        /// 得到Parameters,里面会根据 ","来分割
        /// </summary>
        /// <param name="stParms"></param>
        /// <returns></returns>
        private List<SugarParameter> GetParameters(string stParms)
        {
            List<SugarParameter> sps = new List<SugarParameter>();
            if (!string.IsNullOrEmpty(stParms))
            {
                var ps = stParms.Trim().Split(',');
                foreach (var p in ps)
                {

                    if (p.ToUpper() == "@ID")
                    {
                        SugarParameter psid = new SugarParameter("@Id", id);
                        sps.Add(psid);
                    }
                    else if (p.ToLower() == "@rmsg")
                    {
                        SugarParameter psid = new SugarParameter("@rmsg", null, true);
                        sps.Add(psid);
                    }
                    else if (p.ToLower() == "@DialogResult".ToLower())
                    {
                        continue;//这个参数只有在按钮弹出询问框的时候会增加这个
                        //SugarParameter psid = new SugarParameter("rmsg", null, true);
                        //sps.Add(psid);
                    }
                    else if (p == "")
                    {

                    }
                    else
                    {
                        var ctr = this.TSContainer.ContentPanel.Controls.Find(p.Substring(1), true).FirstOrDefault();
                        // ufo 添加新控件 运行时
                        object? value = null;
                        if (ctr != null)
                        {

                            if (ctr is RMCheckBox cbx)
                            {
                                value = cbx.Checked; ;
                            }
                            else if (ctr is RMDateTimePicker dtp)
                            {
                                value = dtp.dateTimePicker1.Value;
                            }
                            else
                            {
                                value = ctr.Text;
                            }
                        }
                        SugarParameter sp = new SugarParameter(p, value);
                        sps.Add(sp);

                    }
                }
            }
            return sps;
        }
        /// <summary>
        /// 根据查询参数字符串生成Parameter
        /// todo 通过正则验证参数是否ok
        /// </summary>
        /// <param name="stParms"></param>
        /// <returns></returns>
        private List<SugarParameter> GetParameters(string stParms, bool addId = false, bool outMsg = false)
        {
            List<SugarParameter> sps = new List<SugarParameter>();
            if (addId)
            {
                SugarParameter psid = new SugarParameter("Id", id);
                sps.Add(psid);
            }
            if (outMsg)
            {
                SugarParameter psid = new SugarParameter("rmsg", null, true);
                sps.Add(psid);
            }
            if (!string.IsNullOrEmpty(stParms))
            {
                var ps = stParms.Trim().Split(',');
                foreach (var p in ps)
                {
                    var ctr = this.TSContainer.ContentPanel.Controls.Find(p, true).FirstOrDefault();
                    // var ty = ctr.GetType();
                    var value = ctr == null ? "" : ctr.Text;
                    SugarParameter sp = new SugarParameter(p, value);
                    sps.Add(sp);
                }
            }
            return sps;
        }

        /// <summary>
        /// 得到table后,赋值给datagridview
        /// </summary>
        /// <param name="dt"></param>
        private void TableChange(DataTable dt)
        {
            var ctr = this.TSContainer.ContentPanel.Controls.Find("dgv", true).FirstOrDefault() as RMDataGridView;
            if (ctr != null)
            {
                ctr.DataSourse = dt;
            }
        }
        /// <summary>
        /// 选择某一行后执行的逻辑
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RowSelect(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0 || e.ColumnIndex < 0)
            {
                return;
            }
            var obj = sender as DataGridView;
            var idd = obj!.Rows[e.RowIndex].Cells["Id"].Value.ToString();
            id = Convert.ToInt32(idd);
            foreach (DataGridViewColumn item in obj.Columns)
            {
                var na = item.Name;
                try
                {
                    var ctr = this.TSContainer.ContentPanel.Controls.Find(na, true).FirstOrDefault();
                    if (ctr != null)
                    {
                        //ufo 不同的控件,赋值方式不一样
                        if (ctr is RMCheckBox cb)
                        {
                            if (bool.TryParse(obj.Rows[e.RowIndex].Cells[na].Value.ToString(), out bool val))
                            {
                                cb.Checked = val;
                            }

                        }
                        else if (ctr is RMRadioButton rb)
                        {
                            if (bool.TryParse(obj.Rows[e.RowIndex].Cells[na].Value.ToString(), out bool val))
                            {
                                rb.Checked = val;
                            }

                        }
                        else
                        {
                            ctr.Text = obj.Rows[e.RowIndex].Cells[na].Value.ToString();
                        }

                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
        }



        private void 导出Excel(object sender, EventArgs e)
        {
            var dgv = this.TSContainer.ContentPanel.Controls.Find("dgv", true).FirstOrDefault() as RMDataGridView;
            if (dgv != null)
            {
                var table = dgv.DataSourse as DataTable;
                if (File.Exists("test.xlsx"))
                {
                    File.Delete("test.xlsx");
                }
                MiniExcel.SaveAs($"test.xlsx", table);
                Process.Start("test.xlsx");
            }


        }

        #endregion Private 方法

    }
}
